package com.brillilab.service.quartz;

import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.exceptions.BrillilabException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;

/**
 * 定时任务管理类
 *
 * @author lj
 */
@Component
@Slf4j
public class BrillQuartzScheduler {

    // 任务调度
    @Resource
    private Scheduler scheduler;

    /**
     * 新建定时任务
     *
     * @param jobClazz
     * @param jobId
     * @param jobGroup
     * @param cronExp
     */
    public void createJob(Class<? extends Job> jobClazz, String jobId, String jobGroup, String cronExp, Map<String, Object> dataMap) {

        try {
            JobDataMap jobDataMap = new JobDataMap(dataMap);

            JobDetail jobDetail = JobBuilder.newJob(jobClazz)
                    .withIdentity(jobId, jobGroup)
                    .usingJobData(jobDataMap)
                    .build();

            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobId, jobGroup)
                    .startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
        } catch (SchedulerException e) {
            log.error("create job failed!", e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobId
     * @param jobGroup
     * @throws SchedulerException
     */
    public void deleteJob(String jobId, String jobGroup) {
        try {
            JobKey jobKey = JobKey.jobKey(jobId, jobGroup);
            if (scheduler.checkExists(jobKey)) {
                scheduler.deleteJob(jobKey);
            }
        } catch (SchedulerException e) {
            log.error("delete job failed!", e);
        }
    }

    /**
     * 获取Job信息
     *
     * @param jobId
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public Date getNextFireTime(String jobId, String jobGroup) throws BrillilabException {
        try {
            TriggerKey triggerKey = new TriggerKey(jobId, jobGroup);
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (cronTrigger == null) {
                return null;
            }
            CronExpression cronExpression = new CronExpression(cronTrigger.getCronExpression());
            return cronExpression.getNextValidTimeAfter(new Date());
        } catch (SchedulerException | ParseException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 获取Job信息
     *
     * @param jobId
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public String getJobInfo(String jobId, String jobGroup) throws BrillilabException {
        try {
            TriggerKey triggerKey = new TriggerKey(jobId, jobGroup);
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (cronTrigger != null) {
                return String.format("time:%s,state:%s", cronTrigger.getCronExpression(),
                        scheduler.getTriggerState(triggerKey).name());
            } else {
                return null;
            }

        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 修改某个任务的执行时间
     *
     * @param jobId
     * @param jobGroup
     * @param cronExp
     * @return
     * @throws SchedulerException
     */
    public boolean modifyJob(String jobId, String jobGroup, String cronExp) throws BrillilabException {
        try {
            Date date = null;
            TriggerKey triggerKey = new TriggerKey(jobId, jobGroup);
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            String oldTime = cronTrigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cronExp)) {
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
                CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobId, jobGroup)
                        .withSchedule(cronScheduleBuilder).build();
                date = scheduler.rescheduleJob(triggerKey, trigger);
            }
            return date != null;
        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 暂停所有任务
     *
     * @throws SchedulerException
     */
    public void pauseAllJob() throws BrillilabException {
        try {
            scheduler.pauseAll();
        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 暂停某个任务
     *
     * @param jobId
     * @param jobGroup
     * @throws SchedulerException
     */
    public void pauseJob(String jobId, String jobGroup) throws BrillilabException {
        try {
            JobKey jobKey = new JobKey(jobId, jobGroup);
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (jobDetail == null)
                return;
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 恢复所有任务
     *
     * @throws SchedulerException
     */
    public void resumeAllJob() throws BrillilabException {
        try {
            scheduler.resumeAll();
        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }

    /**
     * 恢复某个任务
     *
     * @param jobId
     * @param jobGroup
     * @throws SchedulerException
     */
    public void resumeJob(String jobId, String jobGroup) throws BrillilabException {
        try {
            JobKey jobKey = new JobKey(jobId, jobGroup);
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (jobDetail == null)
                return;
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            throw new BrillilabException(ResultEnum.QUARTZ_EXCEPTION);
        }
    }
}
